#ifndef __COROUTINE_TEST_H__
#define __COROUTINE_TEST_H__

#include <coroutine>
#include <iostream>

namespace coroutine_test
{

	class coroutine_test
	{
	public:
		// 协程必须包含-承诺对象(promise)
		class promise_type
		{
		public:
			coroutine_test get_return_object()
			{
				return coroutine_test{ std::coroutine_handle<promise_type>::from_promise(*this) };
			}

			std::suspend_always initial_suspend() { return {}; }

			std::suspend_always final_suspend() noexcept { return {}; }

			void unhandled_exception() { std::terminate(); }

			std::suspend_always yield_value(int value)
			{
				m_current_value = value;

				return {};
			}

			void return_void() { std::cout << __func__ << std::endl; }

			//
		public:
			int m_current_value;
		};

		//
	public:
		explicit coroutine_test(std::coroutine_handle<promise_type> handle)
			: m_coro_handle(handle)
		{
		}

		~coroutine_test()
		{
			if (m_coro_handle)
			{
				m_coro_handle.destroy();
			}
		}

		coroutine_test(const coroutine_test&) = delete;
		coroutine_test& operator=(const coroutine_test&) = delete;

		coroutine_test(coroutine_test&& other) noexcept
			: m_coro_handle(other.m_coro_handle)
		{
			other.m_coro_handle = nullptr;
		}

		coroutine_test& operator=(coroutine_test&& other) noexcept
		{
			if (this != &other)
			{
				m_coro_handle = other.m_coro_handle;
				other.m_coro_handle = nullptr;
			}

			return *this;
		}

		bool move_next()
		{
			if (m_coro_handle.done() == false)
			{
				m_coro_handle.resume();

				return true;
			}

			return false;
		}

		int current_value() const
		{
			auto handle = m_coro_handle.promise();

			return handle.m_current_value;
		}

		//
	public:
		std::coroutine_handle<promise_type> m_coro_handle;
	};

	coroutine_test counter()
	{
		for (int i = 0; i < 5; ++i)
		{
			std::cout << "暂停一小下！" << std::endl;
			co_yield i;
		}

		std::cout << "协程返回！" << std::endl;
		co_return;
	}

	void test()
	{
		coroutine_test gen = counter();
		while (gen.move_next())
		{
			std::cout << gen.current_value() << std::endl;
		}

		std::cout << "coroutine 执行完成！！" << std::endl;
	}
}

#endif
